﻿using System;
using System.Collections.Generic;
using System.Linq;
using GC_FFW.BusinessEntities.Abstractions.Interfaces.Forecast;

namespace GC_FFW.BusinessEntities.Forecast
{
	public class Match : IMatch
	{
		#region IMatch Members

		public string HomeTeamName { get; set; }

		public string AwayTeamName { get; set; }

		public int HomeTeamGoalsCount { get; set; }

		public int AwayTeamGoalsCount { get; set; }

		public int TotalGoalsCount
		{
			get
			{
				return HomeTeamGoalsCount + AwayTeamGoalsCount;
			}
		}

		public string MatchResult
		{
			get
			{
				return GetMatchResult(HomeTeamGoalsCount, AwayTeamGoalsCount);
			}
		}

		public string MatchResultWithNames
		{
			get
			{
				return string.Format(@"{0} {1}:{2} {3}", HomeTeamName, HomeTeamGoalsCount, AwayTeamGoalsCount, AwayTeamName);
			}
		}

		public string MatchResultWithDate
		{
			get
			{
				return string.Format(@"{0} - {1} {2}:{3} {4}", Date.ToShortDateString(), HomeTeamName, HomeTeamGoalsCount, AwayTeamGoalsCount, AwayTeamName);
			}
		}

		public bool HasWinner
		{
			get
			{
				return HomeTeamGoalsCount != AwayTeamGoalsCount;
			}
		}

		public bool IsHomeTeamWin
		{
			get
			{
				return HomeTeamGoalsCount > AwayTeamGoalsCount;
			}
		}

		public bool IsAwayTeamWin
		{
			get
			{
				return HomeTeamGoalsCount < AwayTeamGoalsCount;
			}
		}

		public string WinnerName
		{
			get
			{
				return HasWinner
					? IsHomeTeamWin
						? HomeTeamName
						: IsAwayTeamWin ? AwayTeamName : string.Empty
					: string.Empty;
			}
		}

		public DateTime Date { get; set; }

		public IEnumerable<IGoal> Goals { get; set; }

		public IGoal GetGoal(int number)
		{
			return Goals != null && Goals.Any() && number >= 1 && number <= Goals.Count()
				? Goals.OrderBy(g => g.Time).ElementAt(number - 1)
				: null;
		}

		public IGoal GetGoalByTime(int time)
		{
			return Goals != null && Goals.Any()
				? Goals.FirstOrDefault(g => g.Time == time)
				: null;
		}

		public string GetMatchResultAfterGoal(int goalNumber)
		{
			if (Goals == null || !Goals.Any() || goalNumber < 1 || goalNumber > Goals.Count()) return string.Empty;

			var lastgoal = Goals.OrderBy(g => g.Time).ElementAt(goalNumber - 1);
			if (lastgoal == null) return string.Empty;

			var homeGoalsCount = Goals.Count(g => g.Time <= lastgoal.Time && g.IsHomeTeamGoal);
			var awayGoalsCount = Goals.Count(g => g.Time <= lastgoal.Time && !g.IsHomeTeamGoal);

			return GetMatchResult(homeGoalsCount, awayGoalsCount);
		}

		public string GetGoalscorersAfterGoal(int goalNumber)
		{
			if (Goals == null || !Goals.Any() || goalNumber < 1 || goalNumber > Goals.Count()) return string.Empty;

			var lastgoal = Goals.OrderBy(g => g.Time).ElementAt(goalNumber - 1);
			if (lastgoal == null) return string.Empty;

			var goalscorers =
				Goals.Where(g => g.Time > lastgoal.Time).Select(g => (g.Goalscorer ?? string.Empty).Trim()).Distinct().ToList();
			return string.Join(Common.Constants.Text.Symbols.COMMA, goalscorers);
		}

		public bool IsTeamWin(string teamName)
		{
			return HasWinner &&
				((HomeTeamName == teamName && IsHomeTeamWin)
				||
				(AwayTeamName == teamName && IsAwayTeamWin));
		}

		public int TeamGoalsCount(string teamName)
		{
			return HomeTeamName == teamName
				? HomeTeamGoalsCount
				: AwayTeamName == teamName
					? AwayTeamGoalsCount
					: 0;
		}

		public int OpponentTeamGoalsCount(string teamName)
		{
			return HomeTeamName == teamName
				? AwayTeamGoalsCount
				: AwayTeamName == teamName
					? HomeTeamGoalsCount
					: 0;
		}

		public string OpponentTeamName(string teamName)
		{
			return HomeTeamName == teamName
				? AwayTeamName
				: AwayTeamName == teamName
					? HomeTeamName
					: string.Empty;
		}

		public void Update(IMatch match)
		{
			if (match == null) return;

			HomeTeamName = match.HomeTeamName;
			AwayTeamName = match.AwayTeamName;

			Date = match.Date;

			HomeTeamGoalsCount = match.HomeTeamGoalsCount;
			AwayTeamGoalsCount = match.AwayTeamGoalsCount;

			Goals = (match.Goals ?? new List<IGoal>())
				.Select(g => g.Clone() as IGoal)
				.ToList();
		}

		#endregion

		#region Internal Implementation

		private string GetMatchResult(int homeTeamGoalsCount, int awayTeamGoalsCount)
		{
			return string.Format(@"""{0}:{1}""", homeTeamGoalsCount, awayTeamGoalsCount);
		}

		#endregion

		#region ICloneable Members

		public object Clone()
		{
			return new Match
			{
				HomeTeamName = HomeTeamName != null ? HomeTeamName.Clone() as string : null,
				AwayTeamName = AwayTeamName != null ? AwayTeamName.Clone() as string : null,
				AwayTeamGoalsCount = AwayTeamGoalsCount,
				Date = Date,
				HomeTeamGoalsCount = HomeTeamGoalsCount,
				Goals = Goals != null
					? Goals.Select(g => g.Clone() as IGoal).ToList()
					: new List<IGoal>()
			};
		}

		#endregion
	}
}
